/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 * File Name     : roce_tc.h
 * Version       : v2.0
 * Created       : 2024/5/15
 * Last Modified : 2024/5/15
 * Description   : The definition of RoCE DSCP functions.
 */

#ifndef __ROCE_TC_H__
#define __ROCE_TC_H__

#include <rdma/ib_verbs.h>

/* hiroce3_force_tc feature */
enum {
    TCLASS_MATCH_SRC_ADDR_IP,
    TCLASS_MATCH_DST_ADDR_IP,
    TCLASS_MATCH_SRC_ADDR_IP6,
    TCLASS_MATCH_DST_ADDR_IP6,
    TCLASS_MATCH_TCLASS,
    TCLASS_MATCH_TCLASS_NO_PREFIX,
    TCLASS_MATCH_MAX,
};

struct tclass_match {
    u32 mask;
    u8 s_addr[16];
    u8 d_addr[16];
    u8 d_addr_m[16];
    int tclass; /* Should be always last! */
};

struct tclass_parse_node {
    int (*parse)(const char *str, void *store, void *store_mask);
    int (*compare)(struct tclass_match *match, struct tclass_match *match2,
               bool with_mask);
    size_t (*print)(struct tclass_match *match, char *buf, size_t size);
    const char *pattern;
    size_t v_offset;
    size_t m_offset;
    u32 mask;
};

#define TCLASS_CREATE_PARSE_NODE(type, parse, compare, print, pattern,    \
                 mask, v_member, m_member)        \
    [(type)] = {parse, compare, print, pattern,            \
            offsetof(struct tclass_match, v_member),        \
            offsetof(struct tclass_match, m_member), mask}

enum {
    TCLASS_MATCH_MASK_SRC_ADDR_IP = BIT(TCLASS_MATCH_SRC_ADDR_IP),
    TCLASS_MATCH_MASK_DST_ADDR_IP = BIT(TCLASS_MATCH_DST_ADDR_IP),
    TCLASS_MATCH_MASK_SRC_ADDR_IP6 = BIT(TCLASS_MATCH_SRC_ADDR_IP6),
    TCLASS_MATCH_MASK_DST_ADDR_IP6 = BIT(TCLASS_MATCH_DST_ADDR_IP6),
    TCLASS_MATCH_MASK_TCLASS = BIT(TCLASS_MATCH_TCLASS),
    TCLASS_MATCH_MASK_MAX = BIT(TCLASS_MATCH_MAX),
};

#define TCLASS_MAX_RULES 40
#define TCLASS_MAX_CMD 100

struct roce3_device;
struct roce3_tc_data {
    struct tclass_match rule[TCLASS_MAX_RULES];
    struct mutex lock;
    bool initialized;
    int val;
    struct kobject kobj;
    struct roce3_device *ibdev;
};

int init_tc_sysfs(struct roce3_device *dev);
void cleanup_tc_sysfs(struct roce3_device *dev);
void tclass_get_tclass(struct roce3_device *dev, struct roce3_tc_data *tcd, const struct rdma_ah_attr *ah,
    u8 port, u8 *tclass);

#endif